/*
Copyright (C) 2010  Christoph Schnack 

    This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.
*/
package Storage;

import java.io.*;
import java.util.*;
import GuiTools.GuiTools;
import Mainframe.Mainframe;
import Settings.*;
import Statistics.Statistics;


/**
 * 
 * Holds the vocabulary data and manages their statistics and the saving. 
 * 
 * @author Christoph Schnack
 */


public class Storage{
	private boolean LOADING=true;
	Settings SET;
	Mainframe MAINFRAME;
	Statistics STATISTICS;
	public Vocabulary[] all = null;
	
	public Storage(Mainframe fr){
		MAINFRAME = fr;
	}
	
	public void setLoading(boolean arg){ LOADING=arg;}
	
	public void setMainframe(Mainframe mf){
		MAINFRAME = mf;
	}
	
	public void setStatistics(Statistics stats){
		STATISTICS=stats;
	}
	
	public Statistics getStatistics(){
		return STATISTICS;
	}
	
	public void setSettings(Settings set){
		SET = set;
	}

	public boolean isChanged(){
		//FIXME if Vocabulary was added?!
		//check whether any vocabulary was edited
		if(all.length>0){
			for(Vocabulary v : all){
				if(v.getChanged()) return true;
			}
		}
		GuiTools.unlockVocFiles();
		File f = new File("vocs"+File.separator);
    	String[] files = f.list(new FilenameFilter(){
			public boolean accept(File arg0, String arg1) {
				return arg1.endsWith(".voc");
			}
    	});
    	if(files!=null){
    		//check whether any vocabulary was deleted
	    	for(String file : files){
	    		if(getVocabulary(file.substring(0,file.length()-4))==null){
	    			GuiTools.lockVocFiles();
	    			return true;
	    		}
	    	}
    	}
    	GuiTools.lockVocFiles();
    	return false;
	}
	
	
	public Vocabulary makeVocabulary(String s1,String s2){
		return new Vocabulary(s1,s2,this,SET,false);
	}
	
	public Vocabulary makeVocabulary(String s1,String s2,boolean loading){
		return new Vocabulary(s1,s2,this,SET,loading);
	}

	public Word makeWord(String sec,String tcA, String tcB, Vector<Meaning> mA, Vector<Meaning> mB){
		return new Word(sec, tcA, tcB, mA, mB);
	}


	public Vocabulary[] getVocabularies(){
	    return all;
	}
	
	public Vocabulary[] getVocabulariesWithWords(){
		if(all!=null && all.length>0){
			Vector<Vocabulary> tmp = new Vector<Vocabulary>();
			for(Vocabulary v : all){
				if(v.hasWords()) tmp.add(v);
			}
			if(tmp.size()>0)return tmp.toArray(new Vocabulary[tmp.size()]);
		}
		return null;
	}

	private void changeMadeAtVocabulary(String vocName){
		if(!LOADING){
			if(SET.getAutosave())saveVocabulary(getVocabulary(vocName));
		}
	}
	
	
	public void addWordToVoc(String vocName,Word word){
	    if(all!=null){
			for(int i=0;i<all.length;i++){
			    if(vocName.equals(all[i].getName())){
			    	all[i].addWord(word);
			    	if(!LOADING)STATISTICS.addWordToVocabulary(vocName,word.getName(),STATISTICS.new WordStatistic(),false);
			    	changeMadeAtVocabulary(vocName);
			    	break;
			    }
			}
	    }
	}
	
	public void deleteWord(String vocName,String wdName){
		if(all!=null){
			for(int i=0;i<all.length;i++){
			    if(vocName.equals(all[i].getName())){
			    	all[i].delWord(wdName);
			    	if(!LOADING)STATISTICS.deleteWordFromVocabulary(wdName, vocName);
			    	changeMadeAtVocabulary(vocName);
			    	break;
			    }
			}
	    }
	}
	
	public void editWord(String vocName,Word wordOld,Word wordNew,boolean copyStats){
	    if(all!=null){
			int l = all.length;
			for(int i = 0;i<l;i++){
		    	if(all[i].getName().equals(vocName)){
		    		all[i].replaceWord(wordOld,wordNew);
		    		if(!LOADING)STATISTICS.replaceWordInVocabulary(wordOld.getName(), wordNew.getName(), vocName,copyStats);
		    		changeMadeAtVocabulary(vocName);
		    		break;
		    	}
			}
	    }
	}

	public void editVocabularyName(String oldName, String newName1, String newName2){
		for(int i=0;i<all.length;i++){
			if(oldName.equals(all[i].getName())){
				try{
					all[i].setName(newName1,newName2);
					//update statistics
					STATISTICS.renameVocabulary(oldName,all[i].getName());
					changeMadeAtVocabulary(all[i].getName());
				    if(!LOADING)MAINFRAME.updateMainframe();
				}
				catch(Exception e){
					e.printStackTrace();
				}
				break;
			}
		}
	}
	
	public boolean hasVocabulary(String name){
		for(Vocabulary v : all){
			if(v.getName().equals(name)) return true;
		}
		return false;
	}
		
	public boolean hasVocs(){
		if(all!=null){
			if(all.length>0) return true;
			else return false;
		}
		else return false;
	}
	
	/**
	 * 
	 *@author Christoph Schnack
	 * @param pattern in format "lang1 - lang2"
	 * @return
	 */
	public Vocabulary getVocabulary(String pattern){
	    //search for vocabulary, pattern-string: "lang1 - lang2"
	    if(all!=null){
			int l = all.length;
			for(int i = 0;i<l;i++){
		    	if(all[i].getName().equals(pattern)) return all[i];
			}
	    }
	    return null;
	}

	public void addVocabulary(Vocabulary newV){
	    Vocabulary[] tmp;
	    if(all!=null){
	    	int l = all.length;
	    	tmp = new Vocabulary[l+1];
	    	for(int i=0;i<l;i++){
	    		tmp[i] = all[i];
	    	}
	    }
	    else{
	    	all = new Vocabulary[1];
	    	tmp = new Vocabulary[1];
	    }
	    tmp[tmp.length-1] = newV;
	    all = tmp;
	    changeMadeAtVocabulary(all[all.length-1].getName());
	    if(!LOADING){
	    	STATISTICS.addVocabulary(newV.getName(),true);
	    	MAINFRAME.updateMainframe();
	    }
	}

	public void delVoc(String arg){
	    if(all!=null){
			int length = all.length;
			Vocabulary[] tmp = new Vocabulary[length-1];
			int j = 0;
			for(int i=0;i<length;i++){
			    if(!arg.equals(all[i].getName())){
			   		tmp[j] = all[i];
				   	j++;
		    	}
			}
			all = tmp;
	    	if(SET.getAutosave()){
	    		File f = new File("vocs"+File.separator);
		    	String[] files = f.list(new FilenameFilter(){
					public boolean accept(File arg0, String arg1) {
						return arg1.endsWith(".voc");
					}
		    	});
		    	GuiTools.unlockVocFiles();
		    	for(String file : files){
		    		if(getVocabulary(file.substring(0,file.length()-4))==null){
		    			File delF = new File("vocs"+File.separator+file);
		    			delF.delete();
		    		}
		    	}
		    	GuiTools.lockVocFiles();
	    	}
		    if(!LOADING)MAINFRAME.updateMainframe();
	    }
	}

	public String[] getNamen(){
	    if(all!=null){
			String[] tmp = new String[all.length];
			for(int i=0;i<all.length;i++){
		    	tmp[i] = all[i].getName();
			}
			return tmp;
	   	}
	    else return new String[0];
	}
	
	public String[] getNamesWithWords(){
		if(all!=null && all.length>0){
			Vector<String> tmp = new Vector<String>();
			for(Vocabulary v : all){
				if(v.hasWords()) tmp.add(v.getName());
			}
			if(tmp.size()>0)return tmp.toArray(new String[tmp.size()]);
		}
		return null;
	}
	
	public boolean noWordsAtAll(){
		if(all!=null){
			for(int i=0;i<all.length;i++){
				if(all[i].hasWords()) return false;
			}
			return true;
		}
		else return true;
	}
	
	public void saveIfAutosave(){
		if(SET.getAutosave()) saveAllVocabularies();
	}
	
   /**
    * 
    * Saves all data of MAINVOC in "vocs/" using the vocabularies' names to name their files.
    * 
    */

	public void saveAllVocabularies(){
		Vocabulary[] vocs = getVocabularies();
		if(vocs!=null){
		    try{
		    	for(Vocabulary voc : vocs){
		    		saveVocabulary(voc);
		    	}
		    	File f = new File("vocs"+File.separator);
		    	String[] files = f.list(new FilenameFilter(){
					public boolean accept(File arg0, String arg1) {
						return arg1.endsWith(".voc");
					}
		    	});
		    	GuiTools.unlockVocFiles();
		    	for(String file : files){
		    		if(getVocabulary(file.substring(0,file.length()-4))==null){
		    			File delF = new File("vocs"+File.separator+file);
		    			delF.delete();
		    		}
		    	}
		    	GuiTools.lockVocFiles();
		    }
		    catch(Exception e){e.printStackTrace();}
		}
	}//save
	
	public void saveVocabularyIfAutosave(Vocabulary voc){
		if(!LOADING && SET.getAutosave()) saveVocabulary(voc);
	}
	/**
	 * Saves a vocabulary and its statistics.
	 *@author Christoph Schnack
	 * @param voc
	 */
	public void saveVocabulary(Vocabulary voc){
		boolean writeInLines = SET.getWriteInLines();
		try{
			GuiTools.unlockVocFiles();
			//FIXME all statistics? if changes are made in other vocs?
			if(!STATISTICS.isSaved())STATISTICS.saveStatistics(true);
			if(SET.isVerbose())System.out.print("# try saving :"+voc.getName()+" ... ");
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(GuiTools.TRIBUITHOME+File.separator+"vocs"+File.separator+voc.getName()+".voc"),"UTF-8"));
			writer.write("13="+voc.getNameA()+":"+voc.getNameB()+"=");
			writer.write(voc.getTermclassDataString());
			if(voc.hasWords()){
    			if(writeInLines){
	    			for(Word word : voc.getWords()){
	    				writer.newLine();
	    				writer.write(word.getAllData());
	    				writer.write("#");
	    			}
    			}
    			else{
	    			for(Word word : voc.getWords()){
	    				writer.write(word.getAllData());
	    				writer.write("#");
	    			}
    			}
    		}
    		else writer.write("nowords");
			if(SET.isVerbose())System.out.println("successfully");
			writer.close();
			voc.setChanged(false);
			GuiTools.lockVocFiles();
		}
		catch(Exception e){e.printStackTrace();}
	}
	
}//Storage
